/**
 * @description 
 * @author cq
 * @Date 2020-11-03 16:11:30
 * @LastEditTime 2020-11-04 17:37:50
 * @LastEditors cq
 */
import './App.css';
import React, { useState } from "react";
import produce from 'immer';
import moveStandard from "./utils/move";
import successArr from "./utils/success"


// 存放九宫格以及其中的棋子内容
// id 九宫格编号 content 棋子  name当前点击
const list = [
  {
    id: 1,
    content: "",
    name: ""
  },
  {
    id: 2,
    content: "",
    name: ""
  }, {
    id: 3,
    content: "",
    name: ""
  }, {
    id: 4,
    content: "",
    name: ""
  }, {
    id: 5,
    content: "",
    name: ""
  }, {
    id: 6,
    content: "",
    name: ""
  }, {
    id: 7,
    content: "",
    name: ""
  }, {
    id: 8,
    content: "",
    name: ""
  }, {
    id: 9,
    content: "",
    name: ""
  }
]

let clickXArr = [];//当前点击X存放ID  
let clickOArr = [];//当前点击O存放ID  

let flagBth = false;//用来记录是否点过右边按钮
let flagSucess = false;

function App() {
  const [contentList, setContentList] = useState(list);
  // 维护一个当前点击状态
  const [curObj, setCurObj] = useState({
    flag: true,// true表示o  false表示x   用来判定下一个是什么棋子
    curId: "",//当前点击的方格编号
    sum: 0,//当前方格内棋子数目
  });

  const [historyArr, setHistoryArr] = useState([]);//历史回放记录

  const [index, setIndex] = useState(0);//用来记录回放到哪一步

  const [flagArr, setFlagArr] = useState([]);//当前棋子添加  用来回放的时候改变curObj当前状态

  const [winner, setWinner] = useState("")

  // 高亮的函数
  const highlightFn = (id) => {
    // 某一方第一次点击高亮
    setContentList(produce(contentList, draft => {
      for (let index = 0; index < draft.length; index++) {
        const item = draft[index];
        if (item.id == id) {
          // 同一位置无效多次点击
          if (item.name) {
            console.log("当前位置已选中")
            break
          }
          // 判断是否走的棋子正确  通过上一次点击和这一次的比较
          const prePiece = curObj.flag ? "o" : "x";
          if (item.content == prePiece) {
            console.log("与上步棋子所走重复")
            break
          }
          item.name = "color";
          setCurObj({
            ...curObj,
            // flag: !curObj.flag,
            curId: id,
          })
        } else {
          item.name = ""
        }
      }
    }))
  }

  // 移动函数
  const moveFn = (id) => {
    let piece = ""
    const result = produce(contentList, draft => {
      for (let index = 0; index < draft.length; index++) {
        const element = draft[index];
        // 先把上次的高亮赋值给当前
        if (element.id == id) {
          const curHighlight = contentList.find(item => item.id == curObj.curId);
          element.content = curHighlight.content;
          piece = curHighlight.content;
          // 移动后改变当前位置维护变量
          setCurObj({
            ...curObj,
            flag: !curObj.flag,
            curId: id,
          })
        }
        // 清空高亮的位置
        if (element.id == curObj.curId) {
          element.content = "";
          element.name = "";
        }
      }
    })
    historyFn(result, piece, id)
    setContentList(result)
  }

  const move = (id) => {
    // 棋子移动的标准必须有选中状态
    const obj = contentList.find(item => item.id == id);  //当前点击的
    const isName = contentList.find(item => item.name != "");

    // 判断当前是否有了选中状态的棋子
    if (isName) {
      // 有的话去移动  
      // 移动的前提判断当前位置是否有棋子
      // 同类切换高亮  不同类无效提升
      if (obj.content) {
        // 同类
        if (isName.content == obj.content) {
          highlightFn(id)
          return
        } else {
          // 不同类
          console.log("当前位置已有棋子")
          return
        }
      }
      // 查找高亮的棋子所能移动的范围区间看是否满足  
      const highlight = moveStandard.find(item => item.cur == curObj.curId);

      if (!highlight.arr.includes(id)) {
        console.log("当前移动的位置与规则不符")
        return
      }

      // successArr 在落子之前判断中间是否有棋子 如果有 下一步必须成功或者挪走中间

      // 获取下当前运动的棋子其他的位置
      const curMoveList = []
      contentList.forEach(every => {
        if (every.content === isName.content && every.id != isName.id) {
          curMoveList.push(every.id)
        }
      }
      )
      curMoveList.push(id);
      // 此时curMoveList就是当前移动着的所有位置集合
      // 先判断接下来是否能赢 不能在判断是否同类
      if (successArr.includes(curMoveList.sort().toString())) {
        // 赢了
        moveFn(id)
        flagSucess = true
        setWinner(isName.content)
        console.log(`恭喜 ${isName.content} 获胜`)
        return
      } else {
        // 判断下当前中心位置是不是与当前移动者相同的棋子  如果是则判断是否挪走
        // 符合的话  移动步数
        if (contentList[4].content == isName.content && isName.id != 5) {//同类
          // 挪走
          console.log("根据规则中间棋子不能停留")
        } else {
          moveFn(id)
        }
      }

      // moveStandard
    } else {
      // 没有的话去高亮一个
      if (!obj.content) {
        console.log("请先选中移动的棋子")
        return
      }
      // 第一次高亮
      highlightFn(id)
    }
  }
  const historyFn = (result, piece, id) => {
    // result当前改变后的数组  piece当前字母 id当前ID
    // 点过要清空
    let curHistory = historyArr;
    if (flagBth) {
      // 回放历史步骤 一旦进行点击 清空之后的
      curHistory = produce(historyArr, draft => {
        return draft.slice(0, index)
      })
      flagBth = false;
      // setHistoryArr(curHistory)
    }
    // 历史步数记录
    setHistoryArr([...curHistory, result])
    setFlagArr([...flagArr, { piece, id }]);
  }
  const handClick = (id) => {
    console.log(flagSucess, "老哥，赢了别点了")
    if (flagSucess) {
      return
    }
    if (curObj.sum > 5) {
      // 只能移动不能添加
      move(id)
    } else {
      if (successArr.includes(clickXArr.sort().toString()) || successArr.includes(clickOArr.sort().toString())) {
        flagSucess = true;
        setWinner(flagArr[flagArr.length - 1].piece)
        return
      }
      const obj = contentList.find(item => item.id == id);
      if (obj.content) {
        console.log("当前位置已有棋子,无法下棋")
        return
      }
      // 添加棋子
      let piece = "";//确认要添加的棋子
      if (curObj.flag) {
        piece = "x"
      } else {
        piece = "o"
      }
      const result = produce(contentList, draft => {
        for (let index = 0; index < draft.length; index++) {
          const item = draft[index];
          if (item.id == id) {
            item.content = piece;
            setCurObj({
              flag: !curObj.flag,
              curId: id,
              sum: curObj.sum + 1
            })
          }
        }
      })
      setContentList(result)

      // 回放记录
      historyFn(result, piece, id)
      // 点击的时候判断是否成功
      if (curObj.flag) {
        // o存放
        clickXArr.push(id)
      } else {
        clickOArr.push(id)
      }
    }
  }

  // 回放记录
  const handHistory = (item, i) => {
    flagBth = true;
    // 回放记住当前棋子
    if (i) {
      setCurObj({
        flag: flagArr[i - 1].piece == "o" ? true : false,
        curId: flagArr[i - 1].id,
        sum: i
      })
    } else {
      setCurObj({
        flag: true,
        curId: "",
        sum: 0
      })
    }
    // 回放需要重置当前变量储存
    clickOArr = []
    clickXArr = []
    item.forEach(el => {
      if (el.content == "o") {
        clickOArr.push(el.id)
      }
      if (el.content == "x") {
        clickXArr.push(el.id)
      }
    })

    //点击回放的时候关闭胜利开关  但是不能是最后一次回放
    if (successArr.includes(clickXArr.sort().toString()) || successArr.includes(clickOArr.sort().toString())) {
      flagSucess = true;
      setWinner(flagArr[i - 1].piece)
    } else {
      setWinner("")
      flagSucess = false;
    }
    setIndex(i)
    setContentList(item)
  }

  return (
    <div className="App">
      <div className="box">
        {contentList.map(item => <div
          className={item.name}
          key={item.id}
          onClick={() => { handClick(item.id) }}
        >
          {item.content}
        </div>)
        }
      </div>
      <div className="btnList">
        {winner ? `winner: ${winner}` : `next: ${curObj.flag ? "x" : "o"}`}
        <h6 onClick={() => { handHistory(list, 0) }}>go to game start</h6>
        {historyArr.map((item, index) => <h6
          onClick={() => { handHistory(item, index + 1) }}
          key={index}
        >
          go to move #{index + 1}
        </h6>
        )}
      </div>
    </div>
  );
}

export default App;
